<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>QeePHP 快速入门</title>
<link href="css/base.css" rel="stylesheet" type="text/css">
</head>
<body>

<div id="page">


<div class="guide-section">

  <div class="guide-header">
    <span class="nav">
      <a href="http://qeephp.com/docs/">文档索引</a>
      &raquo;
      <a href="index.html">QeePHP 快速入门</a>
      &raquo;
      <a href="node-users.html">实现用户功能</a>
      &raquo;
      修改密码    </span>
  </div>

  <div class="guide-section-details formatted">

    
<h1>修改密码</h1>

<p>通常，用户登录后修改自己的密码时都要求输入正在使用的密码。因此这次我们不能重用刚刚的
Form_UserLogin 表单了，需要单独建立一个。</p>

<h2>建立表单</h2>

<p>创建文件 app/form/changepasswd.php，内容为：</p>

<pre class="php code"><span class="kw2">class</span> Form_ChangePasswd <span
class="kw2">extends</span> QForm
<span class="br0">&#123;</span>
    <span
class="kw2">function</span> __construct<span class="br0">&#40;</span><span
class="re0">$action</span><span class="br0">&#41;</span>
    <span
class="br0">&#123;</span>
        <span
class="co1">// 调用父类的构造函数</span>
        parent<span
class="sy0">::</span>__construct<span class="br0">&#40;</span><span
class="st_h">'form_changepasswd'</span><span class="sy0">,</span> <span
class="re0">$action</span><span class="br0">&#41;</span><span
class="sy0">;</span>
&nbsp;
        <span
class="co1">// 从配置文件载入表单</span>
        <span
class="re0">$filename</span> <span class="sy0">=</span> <span
class="kw3">rtrim</span><span class="br0">&#40;</span><span
class="kw3">dirname</span><span class="br0">&#40;</span><span
class="kw2">__FILE__</span><span class="br0">&#41;</span><span
class="sy0">,</span> <span class="st_h">'/\\'</span><span
class="br0">&#41;</span> <span class="sy0">.</span> DS <span
class="sy0">.</span> <span class="st_h">'changepasswd_form.yaml'</span><span
class="sy0">;</span>
        <span class="re0">$this</span><span
class="sy0">-&gt;</span><span class="me1">loadFromConfig</span><span
class="br0">&#40;</span>Helper_YAML<span class="sy0">::</span><span
class="me2">loadCached</span><span class="br0">&#40;</span><span
class="re0">$filename</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
        <span
class="co1">// 三个密码字段按照 User 模型的 password 属性来验证</span>
        <span
class="re0">$this</span><span class="br0">&#91;</span><span
class="st_h">'old_password'</span><span class="br0">&#93;</span><span
class="sy0">-&gt;</span><span class="me1">addValidations</span><span
class="br0">&#40;</span>User<span class="sy0">::</span><span
class="me2">meta</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">,</span> <span
class="st_h">'password'</span><span class="br0">&#41;</span><span
class="sy0">;</span>
        <span class="re0">$this</span><span
class="br0">&#91;</span><span class="st_h">'new_password'</span><span
class="br0">&#93;</span><span class="sy0">-&gt;</span><span
class="me1">addValidations</span><span class="br0">&#40;</span>User<span
class="sy0">::</span><span class="me2">meta</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="sy0">,</span> <span class="st_h">'password'</span><span
class="br0">&#41;</span><span class="sy0">;</span>
        <span
class="co1">// 但 new_password2 字段还有一个额外的验证规则，</span>
        <span
class="co1">// 通过 Form_ChangePasswd 对象的 checkNewPassword() 方法进行验证</span>
        <span
class="re0">$this</span><span class="br0">&#91;</span><span
class="st_h">'new_password2'</span><span class="br0">&#93;</span><span
class="sy0">-&gt;</span><span class="me1">addValidations</span><span
class="br0">&#40;</span>User<span class="sy0">::</span><span
class="me2">meta</span><span class="br0">&#40;</span><span
class="br0">&#41;</span><span class="sy0">,</span> <span
class="st_h">'password'</span><span
class="br0">&#41;</span>
                              <span
class="sy0">-&gt;</span><span class="me1">addValidations</span><span
class="br0">&#40;</span><span class="kw3">array</span><span
class="br0">&#40;</span><span class="re0">$this</span><span
class="sy0">,</span> <span class="st_h">'checkNewPassword'</span><span
class="br0">&#41;</span><span class="sy0">,</span> <span
class="st_h">'两次输入的密码必须一致'</span><span
class="br0">&#41;</span><span class="sy0">;</span>
    <span
class="br0">&#125;</span>
&nbsp;
    <span
class="co4">/**
     * 检查两次输入的新密码是否一致
     */</span>
    <span
class="kw2">function</span> checkNewPassword<span class="br0">&#40;</span><span
class="re0">$new_password</span><span class="br0">&#41;</span>
    <span
class="br0">&#123;</span>
        <span class="kw1">return</span> <span
class="br0">&#40;</span><span class="re0">$this</span><span
class="br0">&#91;</span><span class="st_h">'new_password2'</span><span
class="br0">&#93;</span><span class="sy0">-&gt;</span><span
class="me1">value</span> <span class="sy0">==</span> <span
class="re0">$this</span><span class="br0">&#91;</span><span
class="st_h">'new_password'</span><span class="br0">&#93;</span><span
class="sy0">-&gt;</span><span class="me1">value</span><span
class="br0">&#41;</span><span class="sy0">;</span>
    <span
class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span></pre>

<p>这次的表单对象复杂了许多。除了要为三个密码输入字段指定验证规则外，还特别增加一个额外的验证规则。checkNewPassword()
这个方法被用于对 new_password2
字段的验证。这样可以检查两次输入的新密码是否一致。</p>

<p>对于复杂表单的自定义验证规则，都可以采用上述方式实现。</p>

<p>创建修改密码表单的配置文件
app/form/changepasswd_form.yaml：</p>

<pre class="python code"><span
class="co1"># ~form 开头的内容用于指定表单属性</span>
~form:
  <span
class="st0">&quot;_subject&quot;</span>: <span
class="st0">&quot;修改密码&quot;</span>
&nbsp;
old_password:
  _ui: password
  _label: <span
class="st0">&quot;现在使用的密码&quot;</span>
&nbsp;
new_password:
  _ui: password
  _label: <span
class="st0">&quot;新密码&quot;</span>
&nbsp;
new_password2:
  _ui: password
  _label: <span
class="st0">&quot;再次输入新密码&quot;</span></pre>

<h2>添加控制器动作</h2>

<p>修改 users 控制器，加入下列代码：</p>

<pre class="php code"><span class="kw2">function</span> actionChangePasswd<span
class="br0">&#40;</span><span class="br0">&#41;</span>
<span
class="br0">&#123;</span>
    <span class="re0">$form</span> <span
class="sy0">=</span> <span class="kw2">new</span> Form_ChangePasswd<span
class="br0">&#40;</span>url<span class="br0">&#40;</span><span
class="st_h">'users/changepasswd'</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span
class="kw1">if</span> <span class="br0">&#40;</span><span
class="re0">$this</span><span class="sy0">-&gt;</span>_context<span
class="sy0">-&gt;</span><span class="me1">isPOST</span><span
class="br0">&#40;</span><span class="br0">&#41;</span> <span
class="sy0">&amp;&amp;</span> <span class="re0">$form</span><span
class="sy0">-&gt;</span><span class="me1">validate</span><span
class="br0">&#40;</span><span class="re0">$_POST</span><span
class="br0">&#41;</span><span class="br0">&#41;</span>
    <span
class="br0">&#123;</span>
        try
        <span
class="br0">&#123;</span>
            <span
class="co1">// 取得当前用户的信息</span>
            <span
class="re0">$current_user</span> <span class="sy0">=</span> <span
class="re0">$this</span><span class="sy0">-&gt;</span>_app<span
class="sy0">-&gt;</span><span class="me1">currentUser</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="sy0">;</span>
            <span
class="co1">// 修改密码</span>
            User<span
class="sy0">::</span><span class="me2">meta</span><span
class="br0">&#40;</span><span class="br0">&#41;</span><span
class="sy0">-&gt;</span><span class="me1">changePassword</span><span
class="br0">&#40;</span>
                <span
class="re0">$current_user</span><span class="br0">&#91;</span><span
class="st_h">'username'</span><span class="br0">&#93;</span><span
class="sy0">,</span>
                <span class="re0">$form</span><span
class="br0">&#91;</span><span class="st_h">'new_password'</span><span
class="br0">&#93;</span><span class="sy0">-&gt;</span><span
class="me1">value</span><span class="sy0">,</span>
                <span
class="re0">$form</span><span class="br0">&#91;</span><span
class="st_h">'old_password'</span><span class="br0">&#93;</span><span
class="sy0">-&gt;</span><span class="me1">value</span>
            <span
class="br0">&#41;</span><span class="sy0">;</span>
            <span
class="co1">// 重定向浏览器</span>
            <span
class="kw1">return</span> <span class="re0">$this</span><span
class="sy0">-&gt;</span>_redirectMessage<span
class="br0">&#40;</span>
                <span
class="st_h">'修改密码成功'</span><span
class="sy0">,</span>
                <span
class="st_h">'您的登录密码已经成功修改，下次登录请使用新密码。'</span><span
class="sy0">,</span>
                url<span class="br0">&#40;</span><span
class="st_h">'default/index'</span><span class="br0">&#41;</span><span
class="br0">&#41;</span><span class="sy0">;</span>
        <span
class="br0">&#125;</span>
        catch <span
class="br0">&#40;</span>AclUser_WrongPasswordException <span
class="re0">$ex</span><span class="br0">&#41;</span>
        <span
class="br0">&#123;</span>
            <span class="re0">$form</span><span
class="br0">&#91;</span><span class="st_h">'old_password'</span><span
class="br0">&#93;</span><span class="sy0">-&gt;</span><span
class="me1">invalidate</span><span class="br0">&#40;</span><span
class="st_h">'您输入的现用密码不正确'</span><span
class="br0">&#41;</span><span class="sy0">;</span>
        <span
class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span
class="re0">$this</span><span class="sy0">-&gt;</span>_view<span
class="br0">&#91;</span><span class="st_h">'form'</span><span
class="br0">&#93;</span> <span class="sy0">=</span> <span
class="re0">$form</span><span class="sy0">;</span>
    <span
class="re0">$this</span><span class="sy0">-&gt;</span>_viewname <span
class="sy0">=</span> <span class="st_h">'register'</span><span
class="sy0">;</span>
<span class="br0">&#125;</span></pre>

<p>这里我们继续沿用了 register 动作的视图 :)</p>

<p>actionChangePasswd() 中，我们使用 acluser 的 changePassword()
方法来修改密码。如果现有密码出错，将抛出异常。只要捕获异常就可以在界面提示用户输入出错了。</p>

<div class="figure"><img src="images/users-changepasswd-01.png" alt="" />
	<p>输入了错误的密码</p>
</div>

<p>注意这次在重定向浏览器时调用的是 _redirectMessage()
方法。这个方法会通过 redirect_message
视图来显示提示信息，能够让用户注意到操作的结果。如果有必要，可以将注册、登录等方法的重定向操作也改为使用带提示信息的重定向。</p>

<div class="figure"><img src="images/users-changepasswd-02.png" alt="" />
	<p>成功修改密码后的提示信息</p>
</div>

<p>现在用户方面的功能就基本上实现完了。下一节开始，我们将实现任务的管理功能。</p>

<p>$Id: users-change-passwd.texy 2295 2009-03-10 07:48:18Z dualface $</p>

  </div>

  <div class="guide-footer">

    <table border="0" width="100%">
      <tr>
        <td align="left" width="200">
                    &laquo;
          <a href="node-users-login.html">用户登录和注销</a>
          
        </td>

        <td align="center">
          本章：<a href="node-users.html">实现用户功能</a>
          <br />
          <a href="index.html">返回索引页</a>
        </td>

        <td align="right" width="200">
                    <a href="node-acl.html">访问控制</a> 
          &raquo;
                  </td>
      </tr>
    </table>

  </div>

</div>


</div>

</body>
</html>


